\chapter{bsp\+\_\+usart }
\hypertarget{md_bsp_2usart_2bsp__usart}{}\label{md_bsp_2usart_2bsp__usart}\index{bsp\_usart@{bsp\_usart}}
\label{md_bsp_2usart_2bsp__usart_autotoc_md20}%
\Hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md20}%




\href{mailto:neozng1@hnu.edu.cn}{\texttt{neozng1@hnu.\+edu.\+cn}}

\begin{quote}
TODO\+: 增加发送队列以解决短时间内调用{\ttfamily \doxylink{bsp__usart_8c_a12acc10fbb458df894b53534ae66c25d}{USARTSend()}}发生丢包的问题,目前仅支持\+DMA。还需要提供阻塞和\+IT模式以供选择，参考bspiic和spi进行实现。 可以直接在发送函数的参数列表添加发送模式选择,或增加instance成员变量,并提供设置模式接口,两者各有优劣 \end{quote}
\hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md21}{}\doxysection{\texorpdfstring{使用说明}{使用说明}}\label{md_bsp_2usart_2bsp__usart_autotoc_md21}
若你需要构建新的基于串口的module，首先需要拥有一个{\ttfamily usart\+\_\+instance}的指针用于操作串口对象。

需要在串口实例下设定接收的数据包的长度，实例对应的串口硬件（通过{\ttfamily \doxylink{group___u_a_r_t___exported___types_ga5de4a49eb132735325e706f406c69d6e}{UART\+\_\+\+Handle\+Type\+Def}}指定，如{\ttfamily \&huart1}），解析接收数据对应的回调函数这三个参数。然后，调用{\ttfamily \doxylink{bsp__usart_8c_a4296c218240b51944ecb698eed2625ef}{USARTRegister()}}并传入配置好的{\ttfamily usart\+\_\+instance}指针即可。

若要发送数据，调用{\ttfamily \doxylink{bsp__usart_8c_a12acc10fbb458df894b53534ae66c25d}{USARTSend()}}。注意buffsize务必小于你创建的buff的大小，否则造成指针越界后果未知。

串口硬件收到数据时，会将其存入{\ttfamily usart\+\_\+instance.\+recv\+\_\+buff\mbox{[}\mbox{]}}中，当收到完整一包数据，会调用设定的回调函数{\ttfamily module\+\_\+callback}（即你注册时提供的解析函数）。在此函数中，你可以通过{\ttfamily usart\+\_\+instance.\+recv\+\_\+buff\mbox{[}\mbox{]}}访问串口收到的数据。\hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md22}{}\doxysection{\texorpdfstring{代码结构}{代码结构}}\label{md_bsp_2usart_2bsp__usart_autotoc_md22}
.h文件内包括了外部接口和类型定义,以及模块对应的宏。c文件内为私有函数和外部接口的定义。\hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md23}{}\doxysection{\texorpdfstring{类型定义}{类型定义}}\label{md_bsp_2usart_2bsp__usart_autotoc_md23}

\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ DEVICE\_USART\_CNT\ 3\ \ \ \ \ }\textcolor{comment}{//\ C板至多分配3个串口}}
\DoxyCodeLine{\textcolor{preprocessor}{\#define\ USART\_RXBUFF\_LIMIT\ 128\ }\textcolor{comment}{//\ if\ your\ protocol\ needs\ bigger\ buff,\ modify\ here}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ void\ (*usart\_module\_callback)();}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{comment}{/*\ usart\_instance\ struct,each\ app\ would\ have\ one\ instance\ */}}
\DoxyCodeLine{\textcolor{keyword}{typedef}\ \textcolor{keyword}{struct}}
\DoxyCodeLine{\{}
\DoxyCodeLine{\ \ \ \ uint8\_t\ recv\_buff[USART\_RXBUFF\_LIMIT];\ \textcolor{comment}{//\ 预先定义的最大buff大小,如果太小请修改USART\_RXBUFF\_LIMIT}}
\DoxyCodeLine{\ \ \ \ uint8\_t\ recv\_buff\_size;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \textcolor{comment}{//\ 模块接收一包数据的大小}}
\DoxyCodeLine{\ \ \ \ \mbox{\hyperlink{group___u_a_r_t___exported___types_ga5de4a49eb132735325e706f406c69d6e}{UART\_HandleTypeDef}}\ *usart\_handle;\ \ \ \ \ \ \textcolor{comment}{//\ 实例对应的usart\_handle}}
\DoxyCodeLine{\ \ \ \ usart\_module\_callback\ module\_callback;\ \textcolor{comment}{//\ 解析收到的数据的回调函数}}
\DoxyCodeLine{\}\ usart\_instance;}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily DEVICE\+\_\+\+USART\+\_\+\+CNT}是开发板上可用的串口数量。
\item {\ttfamily USART\+\_\+\+RXBUFF\+\_\+\+LIMIT}是串口单次接收的数据长度上限，暂时设为128，如果需要更大的buffer容量，修改该值。
\item {\ttfamily usart\+\_\+module\+\_\+callback()}是模块提供给串口接收中断回调函数使用的协议解析函数指针。对于每个需要串口的模块，需要定义一个这样的函数用于解包数据。
\item 每定义一个{\ttfamily usart\+\_\+instance}，就代表一个串口的\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}实例\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}（对象）。一个串口实例内有接收buffer，单个数据包的大小，该串口对应的{\ttfamily HAL handle}（代表其使用的串口硬件具体是哪一个）以及用于解包数据的回调函数。
\end{DoxyItemize}\hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md24}{}\doxysection{\texorpdfstring{外部接口}{外部接口}}\label{md_bsp_2usart_2bsp__usart_autotoc_md24}

\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{bsp__usart_8c_a4296c218240b51944ecb698eed2625ef}{USARTRegister}}(usart\_instance\ *\_instance);}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{bsp__usart_8c_a12acc10fbb458df894b53534ae66c25d}{USARTSend}}(usart\_instance\ *\_instance,\ uint8\_t\ *send\_buf,\ uint16\_t\ send\_size);}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily USARTRegister}是用于初始化串口对象的接口，module层的模块对象（也应当为一个结构体）内要包含一个{\ttfamily usart\+\_\+instance}。

{\bfseries{在调用该函数之前，需要先对其成员变量{\ttfamily \texorpdfstring{$\ast$}{*}usart\+\_\+handle},{\ttfamily module\+\_\+callback()}以及{\ttfamily recv\+\_\+buff\+\_\+size}进行赋值。}}
\item {\ttfamily \doxylink{bsp__usart_8c_a12acc10fbb458df894b53534ae66c25d}{USARTSend()}}是通过模块通过其拥有的串口对象发送数据的接口，调用时传入的参数为串口实例指针，发送缓存以及此次要发送的数据长度（8-\/bit\texorpdfstring{$\ast$}{*}n)。
\end{DoxyItemize}\hypertarget{md_bsp_2usart_2bsp__usart_autotoc_md25}{}\doxysection{\texorpdfstring{私有函数和变量}{私有函数和变量}}\label{md_bsp_2usart_2bsp__usart_autotoc_md25}
在.\+c文件内设为static的函数和变量


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{static}\ usart\_instance\ *instance[DEVICE\_USART\_CNT];}

\end{DoxyCode}


这是bsp层管理所有串口实例的入口。


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{static}\ \textcolor{keywordtype}{void}\ \mbox{\hyperlink{bsp__usart_8c_ac45bba3591501c066f505a46dbae7e2b}{USARTServiceInit}}(usart\_instance\ *\_instance)}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{group___u_a_r_t___exported___functions___group2_ga925534fb8bf7ca464fd05c982fe4bfa0}{HAL\_UARTEx\_RxEventCallback}}(\mbox{\hyperlink{group___u_a_r_t___exported___types_ga5de4a49eb132735325e706f406c69d6e}{UART\_HandleTypeDef}}\ *huart,\ uint16\_t\ Size)}
\DoxyCodeLine{\textcolor{keywordtype}{void}\ \mbox{\hyperlink{group___u_a_r_t___exported___functions___group2_ga0e0456ea96d55db31de947fb3e954f18}{HAL\_UART\_ErrorCallback}}(\mbox{\hyperlink{group___u_a_r_t___exported___types_ga5de4a49eb132735325e706f406c69d6e}{UART\_HandleTypeDef}}\ *huart)}

\end{DoxyCode}



\begin{DoxyItemize}
\item {\ttfamily \doxylink{bsp__usart_8c_ac45bba3591501c066f505a46dbae7e2b}{USARTService\+Init()}}会被{\ttfamily \doxylink{bsp__usart_8c_a4296c218240b51944ecb698eed2625ef}{USARTRegister()}}调用，开启接收中断
\item {\ttfamily \doxylink{group___u_a_r_t___exported___functions___group2_ga925534fb8bf7ca464fd05c982fe4bfa0}{HAL\+\_\+\+UARTEx\+\_\+\+Rx\+Event\+Callback()}}和{\ttfamily \doxylink{group___u_a_r_t___exported___functions___group2_ga0e0456ea96d55db31de947fb3e954f18}{HAL\+\_\+\+UART\+\_\+\+Error\+Callback()}}都是对\+HAL的回调函数的重定义（原本的callback是{\ttfamily \+\_\+\+\_\+week}修饰的弱定义），前者在发生\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}\+IDLE中断\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}或\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}单次\+DMA传输中断\texorpdfstring{$\ast$}{*}\texorpdfstring{$\ast$}{*}后会被调用（说明收到了完整的一包数据），随后在里面根据中断来源，调用拥有产生了该中断的模块的协议解析函数进行数据解包；后者在串口传输出错的时候会被调用，重新开启接收。 
\end{DoxyItemize}